#ifndef __TCP_SERVER_H__
#define __TCP_SERVER_H__

#include <memory>
#include <functional>
#include "address.h"
#include "iomanager.h"
#include "socket.h"
#include "noncopyable.h"
#include "config.h"

namespace johnsonli
{
    struct TcpServerConf 
    {
        std::vector<std::string> address;
        int keepalive = 0;
        uint64_t timeout = 1000 * 2 * 60;    // 客户端超时没有发数据来，断开连接
        std::string name;   
        int ssl = 0;

        std::string type = "http";      /// 服务器类型，http, ws, rock

        std::string accept_worker;      // 监听
        std::string io_worker;          // io
        std::string process_worker;     // 业务逻辑


        bool isValid() const {
            return !address.empty();
        }

        bool operator==(const TcpServerConf& oth) const 
        {
            return address == oth.address
            && keepalive == oth.keepalive
            && timeout == oth.timeout
            && name == oth.name
            && ssl == oth.ssl
            && type == oth.type
            && accept_worker == oth.accept_worker
            && io_worker == oth.io_worker
            && process_worker == oth.process_worker;
        }
    };

    template<>
    class LexicalCast<std::string, TcpServerConf> {
    public:
        TcpServerConf operator()(const std::string& v) {
            YAML::Node node = YAML::Load(v);
            TcpServerConf conf;
            //conf.id = node["id"].as<std::string>(conf.id);
            conf.type = node["type"].as<std::string>(conf.type);
            conf.keepalive = node["keepalive"].as<int>(conf.keepalive);
            conf.timeout = node["timeout"].as<int>(conf.timeout);
            conf.name = node["name"].as<std::string>(conf.name);
            conf.ssl = node["ssl"].as<uint64_t>(conf.ssl);
            //conf.cert_file = node["cert_file"].as<std::string>(conf.cert_file);
            //conf.key_file = node["key_file"].as<std::string>(conf.key_file);
            conf.accept_worker = node["accept_worker"].as<std::string>();
            conf.io_worker = node["io_worker"].as<std::string>();
            conf.process_worker = node["process_worker"].as<std::string>();
            //conf.args = LexicalCast<std::string
            //    ,std::map<std::string, std::string> >()(node["args"].as<std::string>(""));
            if(node["address"].IsDefined()) {
                for(size_t i = 0; i < node["address"].size(); ++i) {
                    conf.address.push_back(node["address"][i].as<std::string>());
                }
            }
            return conf;
        }
    };

    template<>
    class LexicalCast<TcpServerConf, std::string> {
    public:
        std::string operator()(const TcpServerConf& conf) {
            YAML::Node node;
            //node["id"] = conf.id;
            node["type"] = conf.type;
            node["name"] = conf.name;
            node["keepalive"] = conf.keepalive;
            node["timeout"] = conf.timeout;
            node["ssl"] = conf.ssl;
            //node["cert_file"] = conf.cert_file;
            //node["key_file"] = conf.key_file;
            node["accept_worker"] = conf.accept_worker;
            node["io_worker"] = conf.io_worker;
            node["process_worker"] = conf.process_worker;
            //node["args"] = YAML::Load(LexicalCast<std::map<std::string, std::string>
            //   , std::string>()(conf.args));
            for(auto& i : conf.address) {
                node["address"].push_back(i);
            }
            std::stringstream ss;
            ss << node;
            return ss.str();
        }
    };

    //Tcp监听池
    class TcpServer : public std::enable_shared_from_this<TcpServer>
                    , Noncopyable 
    {
    public:
        typedef std::shared_ptr<TcpServer> ptr;

        TcpServer();

        /**
         * @brief 构造函数
         * @param[in] worker socket客户端工作的协程调度器
         * @param[in] accept_worker 服务器socket执行接收socket连接的协程调度器
         */
        TcpServer(const std::string& servername
                ,johnsonli::IOManager* worker = johnsonli::IOManager::GetThis()
                ,johnsonli::IOManager* io_woker = johnsonli::IOManager::GetThis()
                ,johnsonli::IOManager* accept_worker = johnsonli::IOManager::GetThis());

        /**
         * @brief 析构函数
         */
        virtual ~TcpServer();

        /**
         * @brief 绑定地址
         * @return 返回是否绑定成功
         */
        virtual bool bind(johnsonli::Address::ptr addr, bool ssl = false);

        /**
         * @brief 绑定地址数组
         * @param[in] addrs 需要绑定的地址数组
         * @param[out] fails 绑定失败的地址
         * @return 是否绑定成功
         */
        virtual bool bind(const std::vector<Address::ptr>& addrs
                            ,std::vector<Address::ptr>& fails
                            ,bool ssl = false);


         /**
         * @brief 启动服务
         * @pre 需要bind成功后执行
         */
        virtual bool start();

        /**
         * @brief 停止服务
         */
        virtual void stop();

        /**
         * @brief 返回读取超时时间(毫秒)
         */
        uint64_t getRecvTimeout() const { return m_recvTimeout;}

        /**
         * @brief 返回服务器名称
         */
        std::string getName() const { return m_name;}

        /**
         * @brief 设置读取超时时间(毫秒) 客户端超时没有发数据来，断开连接
         */
        void setRecvTimeout(uint64_t v) { m_recvTimeout = v;}

        /**
         * @brief 设置服务器名称
         */
        virtual void setName(const std::string& v) { m_name = v;}

        /**
         * @brief 是否停止
         */
        bool isStop() const { return m_isStop;}

        std::vector<Socket::ptr> getSocks() const { return m_socks;}

    protected:

        /**
         * @brief 处理新连接的Socket类
         */
        virtual void handleClient(Socket::ptr client);

        /**
         * @brief 开始接受连接
         */
        virtual void startAccept(Socket::ptr sock);

    protected:
        
        std::vector<Socket::ptr> m_socks;    /// 监听Socket数组
        IOManager* m_worker;                 /// 新连接的Socket工作的调度器
        IOManager* m_ioWorker;               /// 处理读写的调度器
        IOManager* m_acceptWorker;           /// 服务器Socket接收连接的调度器
        uint64_t m_recvTimeout;              /// 接收超时时间(毫秒)
        std::string m_name;                  /// 服务器名称  
        std::string m_type = "tcp";          /// 服务器类型
        bool m_isStop;                       /// 服务是否停止
        bool m_ssl = false;

    };

}

#endif